package com.xsd.command;

/**
 * @Description: 遥控器
 * @Author: zhoufuzong
 * @Created: 2021-03-06 15:43:50
 * @Version: 1.1.0
 */

/**
 * 命令模式的注意事项和细节
 * 1) 将发起请求的对象与执行请求的对象解耦。发起请求的对象是调用者，调用者只要
 * 调用命令对象的execute()方法就可以让接收者工作，而不必知道具体的接收者对
 * 象是谁、是如何实现的，命令对象会负责让接收者执行请求的动作，也就是说：”
 * 请求发起者”和“请求执行者”之间的解耦是通过命令对象实现的，命令对象起到
 * 了纽带桥梁的作用。
 * 2) 容易设计一个命令队列。只要把命令对象放到列队，就可以多线程的执行命令
 * 3) 容易实现对请求的撤销和重做
 * 4) 命令模式不足：可能导致某些系统有过多的具体命令类，增加了系统的复杂度，这
 * 点在在使用的时候要注意
 * 5) 空命令也是一种设计模式，它为我们省去了判空的操作。在上面的实例中，如果没
 * 有用空命令，我们每按下一个按键都要判空，这给我们编码带来一定的麻烦。
 * 6) 命令模式经典的应用场景：界面的一个按钮都是一条命令、模拟CMD（DOS命令） 订单的撤销/恢复、触发-反馈机制
 */

public class RemoteController {
    // 命令数组
    Command[] onCommands;
    Command[] offCommands;

    // 执行撤销命令
    Command undoCommand;

    // 构造器

    public RemoteController() {
        onCommands = new Command[5];
        offCommands = new Command[5];

        for (int i = 0; i <5 ; i++) {
            onCommands[i] = new NoCommand();
            offCommands[i] = new NoCommand();

        }
    }

    // 给我们的按钮设置你需要的命令
    public void setCommand(int no,Command onCommand, Command offCommand){
        onCommands[no]=onCommand;
        offCommands[no]=offCommand;
    }

    // 按下开按钮
    public void onButtonWasPush(int no){
        // 找到你按下的开的按钮，并调用对应方法
        onCommands[no].execute();
        // 记录这次动作，用于撤销
        undoCommand= onCommands[no];
    }

    // 按下关的按钮
    public void offButtonWasPush(int no){
        offCommands[no].execute();
        undoCommand = offCommands[no];
    }

    // 按下撤销的按钮
    public void undoButtonWasPushed(){
        undoCommand.undo();
    }
}
